package com.eduagent.xwqeduagent.controller;

import cn.hutool.core.util.ObjectUtil;
import com.eduagent.xwqeduagent.adviser.MyLoggerAdvisor;
import com.eduagent.xwqeduagent.app.agent.LectureAnalysis;
import com.eduagent.xwqeduagent.app.agent.TeacherEditingHandoutAssistant;
import com.eduagent.xwqeduagent.app.teacher.MultimodalGeneration.MultiModGeneration;
import com.eduagent.xwqeduagent.common.BaseResponse;
import com.eduagent.xwqeduagent.common.ResultUtils;
import com.eduagent.xwqeduagent.constant.prompt.generateQuiz;
import com.eduagent.xwqeduagent.exception.ErrorCode;
import com.eduagent.xwqeduagent.exception.ThrowUtils;
import com.eduagent.xwqeduagent.manus.agent.XwqGeneralManus;
import com.eduagent.xwqeduagent.manus.agent.XwqQuizGeneratorManus;
import com.eduagent.xwqeduagent.model.dto.*;
import com.eduagent.xwqeduagent.model.entity.CourseOutline;
import com.eduagent.xwqeduagent.model.vo.*;
import com.eduagent.xwqeduagent.service.TeacherService;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.annotation.Resource;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.api.Advisor;
import org.springframework.ai.chat.model.ChatModel;
import org.springframework.ai.tool.ToolCallback;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
import java.util.List;
import java.util.stream.Collectors;

import com.eduagent.xwqeduagent.app.agent.TeachingGuidanceExpert;
import reactor.core.publisher.Flux;

import java.util.Map;

import static org.springframework.ai.chat.client.advisor.AbstractChatMemoryAdvisor.CHAT_MEMORY_CONVERSATION_ID_KEY;
import static org.springframework.ai.chat.client.advisor.AbstractChatMemoryAdvisor.CHAT_MEMORY_RETRIEVE_SIZE_KEY;

import java.io.IOException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.core.type.TypeReference;
import com.eduagent.xwqeduagent.exception.BusinessException;
import java.util.Collections;
import java.util.HashMap;
import java.util.OptionalDouble;
import java.time.Duration;


@Slf4j
@RestController
@RequestMapping("/teacher")
@RequiredArgsConstructor
public class TeacherController {

    private final TeacherService teacherService;

    private final MultiModGeneration multiModGeneration;

    private final LectureAnalysis lectureAnalysis;

    private final ToolCallback[] allTools;

    private final ChatModel dashscopeChatModel;

    private final TeachingGuidanceExpert teachingGuidanceExpert;

    private final TeacherEditingHandoutAssistant teacherEditingHandoutAssistant;

    private final ObjectMapper objectMapper;

    private final ChatClient chatClient;

    private final Advisor loveAppRagCloudAdvisor;


    /**
     * 课程大纲生成
     * @param courseOutlineRequestDTO
     * @return
     */
    @PostMapping(value = "/generateOutline")
    public BaseResponse<CourseOutline> generateOutline(@RequestBody CourseOutlineRequestDTO courseOutlineRequestDTO) {

        String courseName = courseOutlineRequestDTO.getCourseName();
        String sessionId = courseOutlineRequestDTO.getSessionId();
        // Delegate to service layer
        CourseOutline outline = teacherService.generateClassOutline(courseName,sessionId);

        return ResultUtils.success(outline);
    }


    /**
     * 小节生成讲义
     * @return BaseResponse<String>
     * @param generateHandOutDTO 生成讲义提示词
     */
    @PostMapping(value = "/generateHandOut")
    public BaseResponse<String> generateHandOut(@RequestBody GenerateHandOutDTO generateHandOutDTO){

        String sectionDescription = generateHandOutDTO.getSectionDescription();
        String supplementPrompt = generateHandOutDTO.getSupplementPrompt();
        String sessionId = generateHandOutDTO.getSessionId();
        String format = generateHandOutDTO.getFormat();

        ThrowUtils.throwIf(ObjectUtil.isEmpty(sectionDescription)||ObjectUtil.isEmpty(sessionId),
                ErrorCode.NOT_FOUND_ERROR,"生成课程名称不能为空");

        String prompt = "讲义主题：" + sectionDescription + "补充" + supplementPrompt + "讲义格式" + format;

        String handout = multiModGeneration.GenerateHandout(prompt, sessionId,format);

        return ResultUtils.success(handout);
    }

    /**
     * 小节生成讲义 - 流式输出
     * @return Flux<String> 流式输出的讲义内容
     * @param generateHandOutDTO 生成讲义提示词
     */
    @PostMapping(value = "/generateHandOut/stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public Flux<String> streamGenerateHandOut(@RequestBody GenerateHandOutDTO generateHandOutDTO){
        String sectionDescription = generateHandOutDTO.getSectionDescription();
        String supplementPrompt = generateHandOutDTO.getSupplementPrompt();
        String sessionId = generateHandOutDTO.getSessionId();
        String format = generateHandOutDTO.getFormat();

        ThrowUtils.throwIf(ObjectUtil.isEmpty(sectionDescription)||ObjectUtil.isEmpty(sessionId),
                ErrorCode.NOT_FOUND_ERROR,"生成课程名称不能为空");

        String prompt = "讲义主题：" + sectionDescription + "补充" + supplementPrompt + "讲义格式" + format;

        log.info("开始流式生成讲义，会话ID：{}，主题：{}", sessionId, sectionDescription);
        
        // 调用流式生成方法
        return multiModGeneration.streamGenerateHandoutContent(prompt, sessionId, format);
    }

    /**
     * 实验设计生成
     * @param request 实验设计请求
     * @return 实验设计结果
     */
    @PostMapping("/generateExperiment")
    public BaseResponse<ExperimentalDesign> generateExperiment(@RequestBody ExperimentalDesignDTO request) {
        log.info("开始生成实验设计，标题：{}，会话ID：{}", request.getTitle(), request.getSessionId());
        
        try {
            ExperimentalDesign result = multiModGeneration.ExperimentalDesign(
                    request.getTitle(),
                    request.getSessionId(),
                    request.getExperimentalContent(),
                    request.getSubmitContent(),
                    request.getFormat()
            );
            return ResultUtils.success(result);
        } catch (Exception e) {
            log.error("生成实验设计失败", e);
            return (BaseResponse<ExperimentalDesign>) ResultUtils.error(ErrorCode.SYSTEM_ERROR, e.getMessage());
        }
    }
    
    /**
     * 流式实验设计生成
     * @param request 实验设计请求
     * @return 实验设计内容流
     */
    @PostMapping(value = "/streamExperiment", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public Flux<String> streamExperiment(@RequestBody ExperimentalDesignDTO request) {
        log.info("开始流式生成实验设计，标题：{}，会话ID：{}", request.getTitle(), request.getSessionId());
        
        try {
            return multiModGeneration.streamExperimentalDesignContent(
                    request.getTitle(),
                    request.getSessionId(),
                    request.getExperimentalContent(),
                    request.getSubmitContent(),
                    request.getFormat()
            );
        } catch (Exception e) {
            log.error("流式生成实验设计失败", e);
            return Flux.error(e);
        }
    }

    /**
     * 流式调用 通用Manus 超级智能体
     *
     * @param message
     * @return
     */
    @GetMapping("/manus/chat")
    public SseEmitter doChatWithManus(String message) {
        XwqGeneralManus xwqGeneralManus = new XwqGeneralManus(allTools,dashscopeChatModel);
        return xwqGeneralManus.runStream(message);
    }

    /**
     * 生成习题集接口
     *
     * @param teachingContent 教学内容（可选）
     * @param numQuestions 题目数量
     * @param desiredQuestionTypes 期望的题目类型
     * @param contentFile 上传的文件（可选）
     * @return 完整的习题集合响应
     */
    @PostMapping(value = "/generate/stream",
            consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    public BaseResponse<QuizQuestionSet> generateQuizStream(
            @RequestParam(value = "teachingContent", required = false) String teachingContent,
            @RequestParam(value = "numQuestions", required = false) Integer numQuestions,
            @RequestParam(value = "desiredQuestionTypes", required = false) List<String> desiredQuestionTypes,
            @RequestPart(value = "contentFile", required = false) MultipartFile contentFile) {

        log.info("接收到习题生成请求，内容长度：{}，题目数量：{}，文件：{}",
                teachingContent != null ? teachingContent.length() : 0,
                numQuestions,
                contentFile != null ? contentFile.getOriginalFilename() : "无文件");

        // 调用Service层方法生成习题
        QuizQuestionSet quizQuestionSet = teacherService.generateQuizQuestions(
                teachingContent, numQuestions, desiredQuestionTypes, contentFile);
                
        return ResultUtils.success(quizQuestionSet);
    }
    
    /**
     * 分析讲义接口
     * @param content 讲义内容 (可选)
     * @param userId 用户ID
     * @param sessionId 会话ID
     * @param file 上传的讲义文件 (可选)
     * @return 讲义分析结果
     */
    @PostMapping(value = "/analyzeLecture", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    public BaseResponse<LectureAnalysisResultVO> analyzeLecture(
            @RequestParam(value = "content", required = false) String content,
            @RequestParam(value = "userId", required = false) String userId,
            @RequestParam(value = "sessionId", required = true) String sessionId,
            @RequestPart(value = "file", required = false) MultipartFile file) {

        log.info("接收到讲义分析请求，内容长度：{}，用户ID：{}，会话ID：{}，文件：{}",
                content != null ? content.length() : 0,
                userId,
                sessionId,
                file != null ? file.getOriginalFilename() : "无文件");

        ThrowUtils.throwIf(ObjectUtil.isEmpty(sessionId),
                ErrorCode.PARAMS_ERROR, "会话ID不能为空");

        // 至少需要提供文本内容或文件内容之一
        ThrowUtils.throwIf(ObjectUtil.isEmpty(content) && (file == null || file.isEmpty()),
                ErrorCode.PARAMS_ERROR, "请提供讲义内容或上传讲义文件");

        // 使用默认用户ID如果未提供
        if (ObjectUtil.isEmpty(userId)) {
            userId = "default_user";
        }

        // 调用讲义分析服务
        LectureAnalysisResultVO result = lectureAnalysis.lectureAnalysis(content, userId, sessionId, file);

        return ResultUtils.success(result);
    }

    /**
     * 课堂互动问答与研讨题设计
     * @param requestDTO 互动问答请求
     * @return 互动问答结果
     */
    @PostMapping(value = "/generateInteractiveQA", consumes = MediaType.APPLICATION_JSON_VALUE)
    public BaseResponse<InteractiveQAResultVO> generateInteractiveQA(@RequestBody ClassroomInteractiveQARequestDTO requestDTO) {
        log.info("接收到课堂互动问答与研讨题设计请求：sessionId={}, 标题={}, 内容长度={}",
                requestDTO.getSessionId(),
                requestDTO.getTitle(),
                requestDTO.getHandoutContent() != null ? requestDTO.getHandoutContent().length() : 0);

        // 参数验证
        ThrowUtils.throwIf(ObjectUtil.isEmpty(requestDTO.getSessionId()),
                ErrorCode.PARAMS_ERROR, "会话ID不能为空");
        ThrowUtils.throwIf(ObjectUtil.isEmpty(requestDTO.getHandoutContent()),
                ErrorCode.PARAMS_ERROR, "讲义内容不能为空");

        // 如果标题为空，使用默认标题
        String title = requestDTO.getTitle();
        if (ObjectUtil.isEmpty(title)) {
            title = "课堂互动问答";
        }

        // 调用互动问答生成方法
        InteractiveQAResultVO result = multiModGeneration.ClassroomInteractiveQA(
                requestDTO.getSessionId(),
                requestDTO.getHandoutContent(),
                title
        );

        return ResultUtils.success(result);
    }
    
    /**
     * 流式课堂互动问答与研讨题设计
     * @param requestDTO 互动问答请求
     * @return 互动问答内容流
     */
    @PostMapping(value = "/streamInteractiveQA", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public Flux<String> streamInteractiveQA(@RequestBody ClassroomInteractiveQARequestDTO requestDTO) {
        log.info("接收到流式课堂互动问答请求：sessionId={}, 标题={}, 内容长度={}",
                requestDTO.getSessionId(),
                requestDTO.getTitle(),
                requestDTO.getHandoutContent() != null ? requestDTO.getHandoutContent().length() : 0);
        
        // 参数验证
        ThrowUtils.throwIf(ObjectUtil.isEmpty(requestDTO.getSessionId()),
                ErrorCode.PARAMS_ERROR, "会话ID不能为空");
        ThrowUtils.throwIf(ObjectUtil.isEmpty(requestDTO.getHandoutContent()),
                ErrorCode.PARAMS_ERROR, "讲义内容不能为空");

        // 如果标题为空，使用默认标题
        String title = requestDTO.getTitle();
        if (ObjectUtil.isEmpty(title)) {
            title = "课堂互动问答";
        }
        
        try {
            return multiModGeneration.streamClassroomInteractiveQAContent(
                    requestDTO.getSessionId(),
                    requestDTO.getHandoutContent(),
                    title
            );
        } catch (Exception e) {
            log.error("流式生成课堂互动问答失败", e);
            return Flux.error(e);
        }
    }

    /**
     * 音频内容时间轴总结接口
     * @param requestDTO 包含音频转写内容和会话ID的请求体
     * @return 时间轴总结结果
     */
    @PostMapping(value = "/timelineSummary", consumes = MediaType.APPLICATION_JSON_VALUE)
    public BaseResponse<TimelineSummaryVO> generateTimelineSummary(
            @RequestBody TimelineSummaryRequestDTO requestDTO) {

        log.info("接收到音频时间轴总结请求，会话ID：{}，内容长度：{}",
                requestDTO.getSessionId(),
                requestDTO.getTextContent() != null ? requestDTO.getTextContent().length() : 0);

        // 参数验证
        ThrowUtils.throwIf(ObjectUtil.isEmpty(requestDTO.getSessionId()),
                ErrorCode.PARAMS_ERROR, "会话ID不能为空");
        ThrowUtils.throwIf(ObjectUtil.isEmpty(requestDTO.getTextContent()),
                ErrorCode.PARAMS_ERROR, "音频转写内容不能为空");

        // 调用时间轴总结方法
        TimelineSummaryVO result = multiModGeneration.TimelineSummary(
                requestDTO.getSessionId(),
                requestDTO.getTextContent());

        return ResultUtils.success(result);
    }

    /**
     * 教学反思接口
     * @param requestDTO 教学反思请求参数
     * @return 教学反思结果
     */
    @PostMapping(value = "/teachingReflection", consumes = MediaType.APPLICATION_JSON_VALUE)
    public BaseResponse<String> generateTeachingReflection(
            @RequestBody TeachingReflectionRequestDTO requestDTO) {

        log.info("接收到教学反思请求，会话ID：{}，内容长度：{}",
                requestDTO.getSessionId(),
                requestDTO.getTextContent() != null ? requestDTO.getTextContent().length() : 0);

        // 参数验证
        ThrowUtils.throwIf(ObjectUtil.isEmpty(requestDTO.getSessionId()),
                ErrorCode.PARAMS_ERROR, "会话ID不能为空");
        ThrowUtils.throwIf(ObjectUtil.isEmpty(requestDTO.getTextContent()),
                ErrorCode.PARAMS_ERROR, "音频转写内容不能为空");

        // 调用教学反思方法
        String reflectionResult = multiModGeneration.TeachingReflection(
                requestDTO.getSessionId(),
                requestDTO.getTextContent());

        return ResultUtils.success(reflectionResult);
    }

    /**
     * 教学改进指导接口
     * 分析教师教学情况并提供改进建议和资源推荐
     * @return 教学改进分析结果
     */
    @PostMapping(value = "/teachingImprovement")
    public BaseResponse<TeachingImprovementResultVO> provideTeachingImprovement(
            @RequestParam(value = "userQuestion", required = false) String userQuestion,
            @RequestParam(value = "userId", required = false) String userId,
            @RequestParam(value = "sessionId", required = true) String sessionId,
            @RequestPart(value = "attachment", required = false) MultipartFile attachment) {


        // 参数验证
        ThrowUtils.throwIf(ObjectUtil.isEmpty(sessionId),
                ErrorCode.PARAMS_ERROR, "会话ID不能为空");

        // 验证至少有用户提问或附件其中之一
        ThrowUtils.throwIf(ObjectUtil.isEmpty(userQuestion) && attachment == null,
                ErrorCode.PARAMS_ERROR, "用户提问和附件不能同时为空");

        // 使用默认用户ID如果未提供
        if (ObjectUtil.isEmpty(userId)) {
            userId = "default_user";
        }

        // 调用教学指导专家服务
        TeachingImprovementResultVO result = teachingGuidanceExpert.provideTeachingGuidance(
                userQuestion,
                userId,
                sessionId,
                attachment
        );

        return ResultUtils.success(result);
    }

    /**
     * 讲义编辑助手接口
     * 分析教师讲义内容、提供编辑建议和修改后的内容
     * @param handoutContent 讲义内容
     * @param userQuestion 用户编辑要求
     * @param userId 用户ID
     * @param sessionId 会话ID
     * @param attachment 上传的附件（如参考文档等）
     * @param skillType 技能类型（1-6，对应不同技能，null表示普通编辑）
     * @return 讲义编辑结果
     */
    @PostMapping(value = "/editHandout",
            consumes = {MediaType.MULTIPART_FORM_DATA_VALUE, MediaType.APPLICATION_FORM_URLENCODED_VALUE})
    public BaseResponse<HandoutEditingResultVO> editHandout(
            @RequestParam(value = "handoutContent", required = true) String handoutContent,
            @RequestParam(value = "userQuestion", required = false) String userQuestion,
            @RequestParam(value = "userId", required = false) String userId,
            @RequestParam(value = "sessionId", required = true) String sessionId,
            @RequestPart(value = "attachment", required = false) MultipartFile attachment,
            @RequestParam(value = "skillType", required = false) String skillType) {

        log.info("接收到讲义编辑请求，内容长度：{}，用户ID：{}，会话ID：{}，文件：{}，技能类型：{}",
                handoutContent != null ? handoutContent.length() : 0,
                userId,
                sessionId,
                attachment != null ? attachment.getOriginalFilename() : "无文件",
                skillType);

        // 参数验证
        ThrowUtils.throwIf(ObjectUtil.isEmpty(sessionId),
                ErrorCode.PARAMS_ERROR, "会话ID不能为空");
        ThrowUtils.throwIf(ObjectUtil.isEmpty(handoutContent),
                ErrorCode.PARAMS_ERROR, "讲义内容不能为空");

        // 使用默认用户ID如果未提供
        if (ObjectUtil.isEmpty(userId)) {
            userId = "default_user";
        }

        // 调用讲义编辑助手服务
        HandoutEditingResultVO result = teacherEditingHandoutAssistant.provideHandoutEditing(
                handoutContent,
                userQuestion,
                userId,
                sessionId,
                attachment,
                skillType
        );

        return ResultUtils.success(result);
    }

    /**
     * 教学计划生成
     * @param requestDTO 教学计划请求参数
     * @return 教学计划内容
     */
    @PostMapping("/generateTeachingPlan")
    public BaseResponse<String> generateTeachingPlan(@RequestBody TeachingPlanRequestDTO requestDTO) {
        log.info("接收到教学计划生成请求：sessionId={}, 大纲内容长度={}",
                requestDTO.getSessionId(),
                requestDTO.getOutlineContent() != null ? requestDTO.getOutlineContent().length() : 0);

        // 参数验证
        ThrowUtils.throwIf(ObjectUtil.isEmpty(requestDTO.getSessionId()),
                ErrorCode.PARAMS_ERROR, "会话ID不能为空");
        ThrowUtils.throwIf(ObjectUtil.isEmpty(requestDTO.getOutlineContent()),
                ErrorCode.PARAMS_ERROR, "教学大纲内容不能为空");

        // 构建完整的请求内容
        StringBuilder requestContent = new StringBuilder();
        requestContent.append("教学大纲内容：").append(requestDTO.getOutlineContent()).append("\n");
        
        if (!ObjectUtil.isEmpty(requestDTO.getTargetAudience())) {
            requestContent.append("目标学生群体：").append(requestDTO.getTargetAudience()).append("\n");
        }
        
        if (requestDTO.getCourseDuration() != null && requestDTO.getCourseDuration() > 0) {
            requestContent.append("课程总时长：").append(requestDTO.getCourseDuration()).append("分钟\n");
        }
        
        if (!ObjectUtil.isEmpty(requestDTO.getAdditionalInfo())) {
            requestContent.append("补充说明：").append(requestDTO.getAdditionalInfo()).append("\n");
        }

        // 调用教学计划生成方法
        String result = multiModGeneration.TeachingPlan(
                requestDTO.getSessionId(),
                requestContent.toString()
        );

        return ResultUtils.success(result);
    }
    
    /**
     * 流式教学计划生成
     * @param requestDTO 教学计划请求参数
     * @return 教学计划内容流
     */
    @PostMapping(value = "/streamTeachingPlan", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public Flux<String> streamTeachingPlan(@RequestBody TeachingPlanRequestDTO requestDTO) {
        log.info("接收到流式教学计划生成请求：sessionId={}, 大纲内容长度={}",
                requestDTO.getSessionId(),
                requestDTO.getOutlineContent() != null ? requestDTO.getOutlineContent().length() : 0);

        // 参数验证
        ThrowUtils.throwIf(ObjectUtil.isEmpty(requestDTO.getSessionId()),
                ErrorCode.PARAMS_ERROR, "会话ID不能为空");
        ThrowUtils.throwIf(ObjectUtil.isEmpty(requestDTO.getOutlineContent()),
                ErrorCode.PARAMS_ERROR, "教学大纲内容不能为空");

        // 构建完整的请求内容
        StringBuilder requestContent = new StringBuilder();
        requestContent.append("教学大纲内容：").append(requestDTO.getOutlineContent()).append("\n");
        
        if (!ObjectUtil.isEmpty(requestDTO.getTargetAudience())) {
            requestContent.append("目标学生群体：").append(requestDTO.getTargetAudience()).append("\n");
        }
        
        if (requestDTO.getCourseDuration() != null && requestDTO.getCourseDuration() > 0) {
            requestContent.append("课程总时长：").append(requestDTO.getCourseDuration()).append("分钟\n");
        }
        
        if (!ObjectUtil.isEmpty(requestDTO.getAdditionalInfo())) {
            requestContent.append("补充说明：").append(requestDTO.getAdditionalInfo()).append("\n");
        }
        
        try {
            return multiModGeneration.streamTeachingPlanContent(
                    requestDTO.getSessionId(),
                    requestContent.toString()
            );
        } catch (Exception e) {
            log.error("流式生成教学计划失败", e);
            return Flux.error(e);
        }
    }

    /**
     * 智能生成试卷接口
     * 根据提供的配置信息，生成一份完整的试卷（含答案）
     *
     * @param requestDTO 试卷生成请求参数
     * @return 生成的试卷内容
     */
    @PostMapping(value = "/generateExamPaper", consumes = MediaType.APPLICATION_JSON_VALUE)
    public BaseResponse<ExamPaperVO> generateExamPaper(@RequestBody ExamPaperGenerationRequestDTO requestDTO) {
        log.info("接收到智能生成试卷请求，会话ID：{}，科目：{}，难度：{}",
                requestDTO.getSessionId(),
                requestDTO.getSubject(),
                requestDTO.getDifficultyLevel());

        // 参数验证
        ThrowUtils.throwIf(ObjectUtil.isEmpty(requestDTO.getSessionId()),
                ErrorCode.PARAMS_ERROR, "会话ID不能为空");
        ThrowUtils.throwIf(ObjectUtil.isEmpty(requestDTO.getSubject()),
                ErrorCode.PARAMS_ERROR, "考试科目不能为空");
        ThrowUtils.throwIf(ObjectUtil.isEmpty(requestDTO.getContentDescription()),
                ErrorCode.PARAMS_ERROR, "考试内容/知识点描述不能为空");

        // 构建提示词
        StringBuilder promptBuilder = new StringBuilder();
        promptBuilder.append("请根据以下要求生成一份完整的考试试卷（含答案和评分标准）：\n\n");
        
        // 基本信息
        promptBuilder.append("科目：").append(requestDTO.getSubject()).append("\n");
        if (!ObjectUtil.isEmpty(requestDTO.getTitle())) {
            promptBuilder.append("标题：").append(requestDTO.getTitle()).append("\n");
        }
        if (requestDTO.getDuration() != null) {
            promptBuilder.append("考试时长：").append(requestDTO.getDuration()).append("分钟\n");
        }
        if (requestDTO.getTotalScore() != null) {
            promptBuilder.append("总分：").append(requestDTO.getTotalScore()).append("分\n");
        }
        if (!ObjectUtil.isEmpty(requestDTO.getDifficultyLevel())) {
            promptBuilder.append("难度级别：").append(requestDTO.getDifficultyLevel()).append("\n");
        }
        if (!ObjectUtil.isEmpty(requestDTO.getTargetGrade())) {
            promptBuilder.append("考试对象/年级：").append(requestDTO.getTargetGrade()).append("\n");
        }
        
        // 考试内容/知识点
        promptBuilder.append("\n考试内容/知识点：\n").append(requestDTO.getContentDescription()).append("\n");
        
        // 试卷结构
        if (requestDTO.getSectionConfigs() != null && !requestDTO.getSectionConfigs().isEmpty()) {
            promptBuilder.append("\n试卷结构：\n");
            for (ExamPaperGenerationRequestDTO.ExamSectionConfig section : requestDTO.getSectionConfigs()) {
                promptBuilder.append("- ").append(section.getSectionType())
                        .append("：").append(section.getQuestionCount()).append("题，")
                        .append(section.getSectionScore()).append("分");
                if (!ObjectUtil.isEmpty(section.getRequirements())) {
                    promptBuilder.append("，要求：").append(section.getRequirements());
                }
                promptBuilder.append("\n");
            }
        }
        
        // 参考内容
        if (!ObjectUtil.isEmpty(requestDTO.getReferenceContent())) {
            promptBuilder.append("\n参考教学内容：\n").append(requestDTO.getReferenceContent()).append("\n");
        }
        
        // 额外要求
        if (!ObjectUtil.isEmpty(requestDTO.getAdditionalRequirements())) {
            promptBuilder.append("\n额外要求：\n").append(requestDTO.getAdditionalRequirements()).append("\n");
        }
        
        log.info("生成试卷提示词构建完成，长度：{}，将使用多线程多智能体并行生成", promptBuilder.length());
        
        try {
            // 调用多线程多智能体模式生成试卷
            String examPaperJson = multiModGeneration.ExamPaperGeneration(
                    requestDTO.getSessionId(),
                    promptBuilder.toString()
            );
            
            log.info("多智能体并行试卷生成成功，JSON长度: {}", examPaperJson.length());
            
            // 将JSON字符串转换为ExamPaperVO对象
            ExamPaperVO examPaper = objectMapper.readValue(examPaperJson, ExamPaperVO.class);
            
            return ResultUtils.success(examPaper);
            
        } catch (Exception e) {
            log.error("试卷生成失败", e);
            throw new RuntimeException("试卷生成失败: " + e.getMessage());
        }
    }

    /**
     * 流式智能生成试卷接口
     * 使用响应式方法流式返回试卷生成结果，提供更好的用户体验
     *
     * @param requestDTO 试卷生成请求参数
     * @return 响应式数据流，传输生成的试卷内容
     */
    @PostMapping(value = "/generateExamPaper/stream", 
            consumes = MediaType.APPLICATION_JSON_VALUE, 
            produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public Flux<String> generateExamPaperStream(@RequestBody ExamPaperGenerationRequestDTO requestDTO) {
        log.info("接收到流式生成试卷请求，会话ID：{}，科目：{}，难度：{}",
                requestDTO.getSessionId(),
                requestDTO.getSubject(),
                requestDTO.getDifficultyLevel());

        // 参数验证
        ThrowUtils.throwIf(ObjectUtil.isEmpty(requestDTO.getSessionId()),
                ErrorCode.PARAMS_ERROR, "会话ID不能为空");
        ThrowUtils.throwIf(ObjectUtil.isEmpty(requestDTO.getSubject()),
                ErrorCode.PARAMS_ERROR, "考试科目不能为空");
        ThrowUtils.throwIf(ObjectUtil.isEmpty(requestDTO.getContentDescription()),
                ErrorCode.PARAMS_ERROR, "考试内容/知识点描述不能为空");

        // 构建提示词
        StringBuilder promptBuilder = new StringBuilder();
        promptBuilder.append("请根据以下要求生成一份完整的考试试卷（含答案和评分标准）：\n\n");
        
        // 基本信息
        promptBuilder.append("科目：").append(requestDTO.getSubject()).append("\n");
        if (!ObjectUtil.isEmpty(requestDTO.getTitle())) {
            promptBuilder.append("标题：").append(requestDTO.getTitle()).append("\n");
        }
        if (requestDTO.getDuration() != null) {
            promptBuilder.append("考试时长：").append(requestDTO.getDuration()).append("分钟\n");
        }
        if (requestDTO.getTotalScore() != null) {
            promptBuilder.append("总分：").append(requestDTO.getTotalScore()).append("分\n");
        }
        if (!ObjectUtil.isEmpty(requestDTO.getDifficultyLevel())) {
            promptBuilder.append("难度级别：").append(requestDTO.getDifficultyLevel()).append("\n");
        }
        if (!ObjectUtil.isEmpty(requestDTO.getTargetGrade())) {
            promptBuilder.append("考试对象/年级：").append(requestDTO.getTargetGrade()).append("\n");
        }
        
        // 考试内容/知识点
        promptBuilder.append("\n考试内容/知识点：\n").append(requestDTO.getContentDescription()).append("\n");
        
        // 试卷结构
        if (requestDTO.getSectionConfigs() != null && !requestDTO.getSectionConfigs().isEmpty()) {
            promptBuilder.append("\n试卷结构：\n");
            for (ExamPaperGenerationRequestDTO.ExamSectionConfig section : requestDTO.getSectionConfigs()) {
                promptBuilder.append("- ").append(section.getSectionType())
                        .append("：").append(section.getQuestionCount()).append("题，")
                        .append(section.getSectionScore()).append("分");
                if (!ObjectUtil.isEmpty(section.getRequirements())) {
                    promptBuilder.append("，要求：").append(section.getRequirements());
                }
                promptBuilder.append("\n");
            }
        }
        
        // 参考内容
        if (!ObjectUtil.isEmpty(requestDTO.getReferenceContent())) {
            promptBuilder.append("\n参考教学内容：\n").append(requestDTO.getReferenceContent()).append("\n");
        }
        
        // 额外要求
        if (!ObjectUtil.isEmpty(requestDTO.getAdditionalRequirements())) {
            promptBuilder.append("\n额外要求：\n").append(requestDTO.getAdditionalRequirements()).append("\n");
        }
        
        log.info("流式生成试卷提示词构建完成，长度：{}", promptBuilder.toString().length());
        
        // 直接调用多模态生成服务的流式方法
        return multiModGeneration.streamExamPaperGeneration(requestDTO.getSessionId(), promptBuilder.toString());
    }

}


